package com.example.opengl_test00;

import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL10Ext;
import javax.microedition.khronos.opengles.GL11;

import android.opengl.GLES20;
import android.util.Log;

public class Box extends Polygon {
	/**
	 * Number of S axis vertex
	 */
	private int mSVertexs;
	/**
	 * Number of T axis vertex
	 */
	private int mTVertexs;
	
	private int mTextureNumber = 0;
	
	public Box(float width, float height, float depth) {
		mSVertexs = 5;
		mTVertexs = 2;
		
		// vertex buffer
		mNumberOfVertexes = mSVertexs * mTVertexs;
		mVertexBuf = createFloatBuffer(4 * 3 * mNumberOfVertexes);
		mVertexBuf.put(new float[] {  width / 2.0f,  height / 2.0f,  depth / 2.0f });
		mVertexBuf.put(new float[] { -width / 2.0f,  height / 2.0f,  depth / 2.0f });
		mVertexBuf.put(new float[] { -width / 2.0f,  height / 2.0f, -depth / 2.0f });
		mVertexBuf.put(new float[] {  width / 2.0f,  height / 2.0f, -depth / 2.0f });
		mVertexBuf.put(new float[] {  width / 2.0f,  height / 2.0f,  depth / 2.0f });
		
		mVertexBuf.put(new float[] {  width / 2.0f, -height / 2.0f,  depth / 2.0f });
		mVertexBuf.put(new float[] { -width / 2.0f, -height / 2.0f,  depth / 2.0f });
		mVertexBuf.put(new float[] { -width / 2.0f, -height / 2.0f, -depth / 2.0f });
		mVertexBuf.put(new float[] {  width / 2.0f, -height / 2.0f, -depth / 2.0f });
		mVertexBuf.put(new float[] {  width / 2.0f, -height / 2.0f,  depth / 2.0f });
		mVertexBuf.position(0);
		
		// index buffer
		int numberOfTriangles = (mTVertexs - 1) * (mSVertexs - 1) * 2 + 4;
		mIndexBuf = createShortBuffer(numberOfTriangles * 3 * 2);
		
		mIndexBuf.put((short) 0);
		mIndexBuf.put((short) 2);
		mIndexBuf.put((short) 1);
		
		mIndexBuf.put((short) 2);
		mIndexBuf.put((short) 4);
		mIndexBuf.put((short) 3);
		
		for (short k = 0; k < mTVertexs - 1; k++) {
			for (short i = 0; i < mSVertexs - 1; i++) {
				short p1 = (short) (i + k * mSVertexs);
				for (int j = 0; j < 2; j++) {
					if (j == 0)	{
						mIndexBuf.put(p1);
						mIndexBuf.put((short) (p1 + mSVertexs + 1));
						mIndexBuf.put((short) (p1 + mSVertexs));
					} else {
						mIndexBuf.put(p1);
						mIndexBuf.put((short) (p1 + 1));
						mIndexBuf.put((short) (p1 + mSVertexs + 1));
					}
				}
			}
		}
		mIndexBuf.put((short) 5);
		mIndexBuf.put((short) 7);
		mIndexBuf.put((short) 6);
		
		mIndexBuf.put((short) 7);
		mIndexBuf.put((short) 9);
		mIndexBuf.put((short) 8);
		
		mNumberOfIndexes = mIndexBuf.position();
		mIndexBuf.position(0);
		
		// normal buffer
		mNormalBuf = createFloatBuffer(4 * 3 * mNumberOfIndexes * 3);
		// vertex normal
		for (int i = 0; i < mNumberOfVertexes * 3; i += 3) {
			Vertor3f v = new Vertor3f(
					mVertexBuf.get(i + 0),
					mVertexBuf.get(i + 1),
					mVertexBuf.get(i + 2));
			mNormalBuf.put(v.normal().toArray());	// must to be normal
		}
		// plane normal
//		for (int i = 0; i < mNumberOfIndexes - 1; i += 3) {
//			Log.d("Box", "i = " + i);
//			short index = mIndexBuf.get(i + 0);
//			Log.d("Box", "index = " + index);
//			Vertor3f v0 = new Vertor3f(
//					mVertexBuf.get(index * 3 + 0),
//					mVertexBuf.get(index * 3 + 1),
//					mVertexBuf.get(index * 3 + 2));
//			
//			index = mIndexBuf.get(i + 1);
//			Log.d("Box", "index = " + index);
//			Vertor3f v1 = new Vertor3f(
//					mVertexBuf.get(index * 3 + 0),
//					mVertexBuf.get(index * 3 + 1),
//					mVertexBuf.get(index * 3 + 2));
//			
//			index = mIndexBuf.get(i + 2);
//			Log.d("Box", "index = " + index);
//			Vertor3f v2 = new Vertor3f(
//					mVertexBuf.get(index * 3 + 0),
//					mVertexBuf.get(index * 3 + 1),
//					mVertexBuf.get(index * 3 + 2));
//			
//			Vertor3f normal = v1.sub(v0).cross(v2.sub(v0)).normal();
//			Log.d("Box", "v0 = " + v0);
//			Log.d("Box", "v1 = " + v1);
//			Log.d("Box", "v2 = " + v2);
//			Log.d("Box", "normal = " + normal);
//			
//			for (int j = 0; j < 3; j++) {
//				Log.d("Box", "mNormalBuf.position = " + mNormalBuf.position());
//				mNormalBuf.put(normal.toArray());
//			}
//		}
		mNormalBuf.position(0);
		
	}
	
	private FloatBuffer mMaterialEmission = FloatBuffer.wrap(new float[] { 0.0f, 0.0f, 0.0f, 1.0f } );
	private FloatBuffer mMaterialAmbient = FloatBuffer.wrap(new float[] { 0.1f, 0.1f, 0.1f, 1.0f } );
	private FloatBuffer mMaterialDiffuse = FloatBuffer.wrap(new float[] { 0.2f, 0.2f, 0.5f, 1.0f } );
	private FloatBuffer mMaterialSpecular = FloatBuffer.wrap(new float[] { 0.9f, 0.9f, 0.9f, 1.0f } );
	
	public void draw(GL10 gl) {
		// set vertex buffer
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuf);
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		
		// set normal buffer
		gl.glNormalPointer(GL10.GL_FLOAT, 0, mNormalBuf);
		gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
		
		// set texture buffer
		if (mTextureNumber != 0)
		{
			gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuf);
			gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
			gl.glActiveTexture(GL10.GL_TEXTURE0);
		}
		
		gl.glEnable(GL10.GL_COLOR_MATERIAL);
		gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_EMISSION, mMaterialEmission);
		gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_AMBIENT, mMaterialAmbient);
		gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_DIFFUSE, mMaterialDiffuse);
//		gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_SPECULAR, mMaterialSpecular);
//		gl.glMaterialf(GL10.GL_FRONT, GL10.GL_SHININESS, 60.0f);
		
		// draw
		gl.glDrawElements(GL10.GL_TRIANGLES, mNumberOfIndexes, GL10.GL_UNSIGNED_SHORT, mIndexBuf);
		
		// reset client state
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
	}
}
